package com.free4inno.knowledgems.controller;

import com.free4inno.knowledgems.dao.GroupInfoDao;
import com.free4inno.knowledgems.dao.LabelInfoDao;
import com.free4inno.knowledgems.dao.UserDao;
import com.free4inno.knowledgems.domain.GroupInfo;
import com.free4inno.knowledgems.domain.LabelInfo;
import com.free4inno.knowledgems.domain.ResourceES;
import com.free4inno.knowledgems.domain.User;
import com.free4inno.knowledgems.service.LabelService;
import com.free4inno.knowledgems.service.ResourceEsService;
import com.free4inno.knowledgems.utils.Constants;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

import javax.servlet.http.HttpSession;

import java.util.*;

/**
 * SearchController.
 */

@Slf4j
@Controller
@RequestMapping("search")
public class SearchController {

    @Autowired
    private UserDao userDao;

    @Autowired
    private GroupInfoDao groupInfoDao;

    @Autowired
    private LabelInfoDao labelInfoDao;

    @Autowired
    private LabelService labelService;

    @Autowired
    private ResourceEsService esService;

    //跳转搜索结果页面
    @RequestMapping("searchAll")
    public String searchAll(@RequestParam("queryStr") String queryStr,
                            @RequestParam("groupIds") String groupIds,
                            @RequestParam("labelIds") String labelIds,
                            @RequestParam("times") int times,
                            Map param, HttpSession session) {
        log.info(this.getClass().getName()+"----in----"+"搜索资源(searchAll)"+"----"+session.getAttribute(Constants.USER_ID));
        param.put("queryStr", queryStr);
        param.put("groupIds", groupIds);
        param.put("labelIds", labelIds);
        param.put("times", times);
        log.info(this.getClass().getName()+"----out----"+"跳转搜索结果页面"+"----"+session.getAttribute(Constants.USER_ID));
        return "search/searchresult";
    }

    //异步传输搜索结果列表
    @RequestMapping("searchdata")
    public String searchdata(@RequestParam("queryStr") String queryStr,
                             @RequestParam("page") int page,
                             @RequestParam("groupIds") ArrayList<String> groupIds,
                             @RequestParam("labelIds") ArrayList<String> labelIds,
                             @RequestParam("searchTimes") int searchTimes,
                             Map param, HttpSession session) {
        log.info(this.getClass().getName()+"----in----"+"异步传输搜索结果列表(searchdata)"+"----"+session.getAttribute(Constants.USER_ID));

        //取搜索条件中分类的name、uplevelid、id等信息
        log.info(this.getClass().getName()+"----"+"取搜索条件中分类的name、uplevelid、id等信息"+"----"+session.getAttribute(Constants.USER_ID));
        ArrayList<ArrayList<Map<String, Object>>> searchLabelInfos = labelService.switchLabelInfos(labelIds);

        //取搜索条件中“群组”的name
        log.info(this.getClass().getName()+"----"+"取搜索条件中“群组”的name"+"----"+session.getAttribute(Constants.USER_ID));
        String searchGroupNames = "";
        for (int i = 0; i < groupIds.size(); i++) {
            int id = Integer.parseInt(groupIds.get(i));
            GroupInfo groupInfo = groupInfoDao.findById(id).orElse(new GroupInfo());
            if (groupInfo.getGroupName() != null) {
                String gn = groupInfo.getGroupName();
                searchGroupNames = searchGroupNames + "," + gn;
            } else {
                searchGroupNames = searchGroupNames + "," + "未知群组" + id;
            }
        }
        if (!searchGroupNames.equals("")) {
            searchGroupNames = searchGroupNames.substring(1);
        }

        //判断登录状态
        log.info(this.getClass().getName()+"----"+"判断登录状态"+"----"+session.getAttribute(Constants.USER_ID));
        Boolean login = true;
        if (session.getAttribute(Constants.ACCOUNT) == null) {
            login = false; //未登录
            log.info(this.getClass().getName()+"----"+"未登录用户"+"----");
        }
        else{
            log.info(this.getClass().getName()+"----"+"已登录用户"+"----"+session.getAttribute(Constants.USER_ID));
        }

        //ES搜索
        log.info(this.getClass().getName()+"----"+"ES搜索"+"----"+session.getAttribute(Constants.USER_ID));
        int size = 10;
        Page<ResourceES> resourceESPage = esService.searchResourceES(page, size, queryStr, groupIds, searchLabelInfos, searchTimes, login);

        //取pageSize
        long recordNum = resourceESPage.getTotalElements();
        long pageSize;
        if (recordNum % size == 0) {
            pageSize = recordNum / size;
        } else {
            pageSize = recordNum / size + 1;
        }

        //遍历搜索结果获取搜索结果列表中展示的标题、正文、作者名、群组名、标签名等信息
        log.info(this.getClass().getName()+"----"+"遍历结果列表获取结果信息"+"----"+session.getAttribute(Constants.USER_ID));
        List<ResourceES> resourceESList = resourceESPage.getContent();

        // 1. build 3 hash set to De-duplication : author, label, group
        HashSet<Integer> usersId = new HashSet<>();
        HashSet<Integer> labelsId = new HashSet<>();
        HashSet<Integer> groupsId = new HashSet<>();
        for (ResourceES resourceES : resourceESList) {
            // 1.1. author
            if (resourceES.getUser_id() != null){
                int userId = resourceES.getUser_id();
                usersId.add(userId);
            }
            // 1.2. label
            if (resourceES.getLabel_id() != null && !resourceES.getLabel_id().equals("")) {
                String[] label = resourceES.getLabel_id().split(",|，");
                for (String s : label) {
                    int labelId = (s == "" ? 0 : Integer.parseInt(s));
                    labelsId.add(labelId);
                }
            }
            // 1.3. group
            if (resourceES.getGroup_id() != null && !resourceES.getGroup_id().equals("")) {
                String[] group = resourceES.getGroup_id().split(",|，");
                for (String s : group) {
                    int groupId = (s == "" ? 0 : Integer.parseInt(s));
                    groupsId.add(groupId);
                }
            }
        }

        // 2. build 3 hash map to save all string names
        HashMap<Integer, String> usersName = new HashMap<>();
        HashMap<Integer, String> labelsName = new HashMap<>();
        HashMap<Integer, String> groupsName = new HashMap<>();
        // 2.1. author
        for (Integer userId : usersId){
            User user = userDao.findById(userId).orElse(new User());
            if (user.getRealName() != null) {
                usersName.put(userId, user.getRealName());
            } else {
                usersName.put(userId, "自邮之翼" + userId);
            }
        }
        // 2.2. label
        for (Integer labelId : labelsId){
            LabelInfo labelInfo = labelInfoDao.findById(labelId).orElse(new LabelInfo());
            if (labelInfo.getLabelName() != null) {
                String ln = labelInfo.getLabelName();
                labelsName.put(labelId, ln);
            } else {
                labelsName.put(labelId, "未知标签" + labelId);
            }
        }
        // 2.3. group
        for (Integer groupId : groupsId){
            GroupInfo groupInfo = groupInfoDao.findById(groupId).orElse(new GroupInfo());
            if (groupInfo.getGroupName() != null) {
                String gn = groupInfo.getGroupName();
                groupsName.put(groupId, gn);
            } else {
                groupsName.put(groupId, "未知群组" + groupId);
            }
        }

        // 3. use names in map, reduce interactions with DB
        for (ResourceES resourceES : resourceESList) {
            String text = resourceES.getText();
            String title = resourceES.getTitle();
            resourceES.setText(text.replaceAll("<.*?>", ""));
            resourceES.setTitle(title.replaceAll("<.*?>", ""));
            //取作者名
            if (resourceES.getUser_id() != null){
                int userId = resourceES.getUser_id();
                resourceES.setUser_name(usersName.get(userId));
            }
            //取群组名
            String groupName = "";
            if (resourceES.getGroup_id() != null && !resourceES.getGroup_id().equals("")) {
                String[] group = resourceES.getGroup_id().split(",|，");
                for (String s : group) {
                    int groupId = (s == "" ? 0 : Integer.parseInt(s));
                    groupName = groupName + "," + groupsName.get(groupId);
                }
                groupName = groupName.substring(1);
            } else {
                groupName = "该资源无群组";
            }
            resourceES.setGroup_name(groupName);
            //取标签名
            String labelName = "";
            if (resourceES.getLabel_id() != null && !resourceES.getLabel_id().equals("")) {
                String[] label = resourceES.getLabel_id().split(",|，");
                for (String s : label) {
                    int labelId = (s == "" ? 0 : Integer.parseInt(s));
                    labelName = labelName + "," + labelsName.get(labelId);
                }
                labelName = labelName.substring(1);
            } else {
                labelName = "该资源无标签";
            }
            resourceES.setLabel_name(labelName);
        }

        param.put("queryStr", queryStr);
        param.put("groupIds", groupIds);
        param.put("labelIds", labelIds);

        param.put("pageSize", pageSize);
        param.put("resourceESList", resourceESList);
        param.put("recordNum", recordNum);

        param.put("searchGroupNames", searchGroupNames);
        param.put("searchLabelInfos", searchLabelInfos);

        log.info(this.getClass().getName()+"----out----"+"资源搜索结束，返回搜索结果"+"----"+session.getAttribute(Constants.USER_ID));
        return "search/_result";
    }
}
